package dataPool;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Vector;

/**
 * 线程池实现
 * Created by Administrator on 2018/6/11.
 */
public class MyPoolImpl implements IMyPool {
    String jdbcdriver;
    String url;
    String userName;
    String passwd;

    int initCount;
    int stepSize;
    int maxSize;
    //连接的集合  线程安全
    Vector<PoolConnnection> poolConnnections = new Vector<PoolConnnection>();

    public MyPoolImpl() {
        init();
    }

    void init() {
        //从配置文件当中获取参数
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("myJDBCPool.properties");
        Properties properties = new Properties();
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        jdbcdriver = properties.getProperty("jdbcDriver");
        url = properties.getProperty("url");
        userName = properties.getProperty("userName");
        passwd = properties.getProperty("password");
        initCount = Integer.parseInt(properties.getProperty("initCount"));
        stepSize = Integer.parseInt(properties.getProperty("stepSize"));
        maxSize = Integer.parseInt(properties.getProperty("poolMaxSize"));
        //创建连接

        //d得到mysql驱动
        try {
            Driver driver = (Driver) Class.forName(jdbcdriver).newInstance();
            //注册驱动
            DriverManager.registerDriver(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //注册驱动之后创建初始化的连接
        createConnection(initCount);

    }

    /**
     * 创建指定数量的连接
     */
    public void createConnection(int count) {
        //检查已有数量加上要创建的数量是否会超过最大值
        if (poolConnnections.size() + count > maxSize) {
            throw new RuntimeException("将超过最大线程数量，创建失败");
        }
        try {
            for (int i = 0; i < count; i++) {
                //使用驱动管理创建连接
                Connection connection = DriverManager.getConnection(url, userName, passwd);
                //放入到自定义连接当中
                PoolConnnection poolConnnection = new PoolConnnection(connection, false);
                //放入到集合当中
                poolConnnections.add(poolConnnection);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取数据库连接
     */
    public PoolConnnection getConnection() {
        //可以检查是否存在连接TODO

        //得到没被占用的连接
        PoolConnnection poolConnnection = getFreeConnection();
        //如果没有得到连接 则创建更多的
        //用循环防止高并发下创建更多之后依然被全部占用没有获取到空闲的连接
        while (poolConnnection == null) {
            createConnection(stepSize);
            //创建之后再次获取没被占用的连接
            poolConnnection = getFreeConnection();
            //sleep一段时间 防止
        }

        return  poolConnnection;
    }

    //得到没被占用的连接 使用同步锁
    private synchronized PoolConnnection getFreeConnection() {
        for (PoolConnnection poolConnnection : poolConnnections) {
            if (!poolConnnection.isBusy()) {
                //未被占用
                //检查自定义连接当中的实际连接是否还存活，没存活则重新创建实际连接
                try {
                    Connection con = poolConnnection.getConnection();
                    //在2000秒之内检查该连接是否失效
                    if (!con.isValid(2000)) {
                        //失效了则重置此实际连接
                        Connection connection = DriverManager.getConnection(url, userName, passwd);
                        poolConnnection.setConnection(connection);
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }

                poolConnnection.setBusy(true);
                return poolConnnection;
            }
        }

        return null;
    }
}
